//===============================================================================
// Microsoft Architecture Strategy Team
// LitwareHR - SaaS Sample Application
//===============================================================================
// Copyright  Microsoft Corporation.  All rights reserved.
// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY
// OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT
// LIMITED TO THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
// FITNESS FOR A PARTICULAR PURPOSE.
//===============================================================================
// The example companies, organizations, products, domain names,
// e-mail addresses, logos, people, places, and events depicted
// herein are fictitious.  No association with any real company,
// organization, product, domain name, email address, logo, person,
// places, or events is intended or should be inferred.
//===============================================================================


namespace Shp.Runtime.OfflineSitka
{
    using System;
    using System.Collections.Generic;
    using System.Xml;
    using System.ServiceModel;
    using System.Globalization;
    using Shp.Runtime.Sitka.ServiceGateway.SitkaClient;

    public static class OfflineSitkaHelper
    {
        public static FaultException<Error> CreateFaultException(Exception ex)
        {
            Error err = new Error();
            err.Message = ex.Message;
            err.StatusCode = ErrorCodes.UnknownError;
            return new FaultException<Error>(err, ex.ToString());
        }

        public static string SerializeEntity(Entity entity)
        {
            XmlDocument xmlEntity = new XmlDocument();

            XmlElement root = xmlEntity.CreateElement("entity");
            xmlEntity.AppendChild(root);

            foreach (string key in entity.Properties.Keys)
            {
                XmlElement xmlProp = xmlEntity.CreateElement("field");
                XmlAttribute xmlName = xmlEntity.CreateAttribute("name");
                XmlAttribute xmlType = xmlEntity.CreateAttribute("type");
                xmlName.InnerText = key;
                xmlType.InnerText = entity.Properties[key].GetType().ToString();
                xmlProp.Attributes.Append(xmlName);
                xmlProp.Attributes.Append(xmlType);

                if (xmlType.InnerText == "System.DateTime")
                {
                    xmlProp.InnerText = ((DateTime)entity.Properties[key]).ToFileTimeUtc().ToString(CultureInfo.InvariantCulture);
                }
                else
                {
                    xmlProp.InnerText = entity.Properties[key].ToString();
                }
                root.AppendChild(xmlProp);
            }

            return xmlEntity.OuterXml;
        }

        public static Entity DeserializeEntity(string xml)
        {
            XmlDocument xmlEntity = new XmlDocument();
            xmlEntity.LoadXml(xml);

            Entity entity = new Entity();
            entity.Properties = new Dictionary<string, object>();

            foreach (XmlElement el in xmlEntity.SelectSingleNode("entity").ChildNodes)
            {
                entity.Properties.Add(el.GetAttribute("name"), GetValue(el));
            }

            return entity;
        }

        private static object GetValue(XmlElement el)
        {
            string attribute = el.Attributes["type"].InnerText;

            switch (attribute)
            {
                case "System.String":
                    return el.InnerText;
                case "System.DateTime":
                    return DateTime.FromFileTimeUtc( long.Parse( el.InnerText, CultureInfo.InvariantCulture) );
                case "System.Decimal":
                    return decimal.Parse(el.InnerText, CultureInfo.InvariantCulture);
                case "System.Boolean":
                    return bool.Parse(el.InnerText);
                default:
                    throw new NotSupportedException("Type: " + attribute + " not supported");
            }
        }
    }
}
